package com.vpen.account.demo.service.impl;


import com.vpen.account.demo.entity.AccountRole;
import com.vpen.account.demo.entity.AccountUser;
import com.vpen.account.demo.model.dto.AccountUserDetails;
import com.vpen.account.demo.service.AccountUserRoleService;
import com.vpen.account.demo.service.AccountUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 优先注入
 *
 * @author 韦鹏
 * @desc 登录请求时springSecurity会调用loadUserByUsername()方法去获取账号相关信息
 * @date 2022/7/15 17:08
 **/
@Slf4j
@Primary
@Service("accountUserDetailService")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class AccountUserDetailServiceImpl implements UserDetailsService {
    private final AccountUserService accountUserService;


    private static AccountUserRoleService ACCOUNT_USER_ROLE_SERVICE;

    @Autowired
    private void setAccountUserRoleService(AccountUserRoleService accountUserRoleService) {
        ACCOUNT_USER_ROLE_SERVICE = accountUserRoleService;
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AccountUser accountUser = accountUserService.selectOneByUsername(username);
        return loadUserDetails(accountUser);
    }


    /***
     * 返回用户的权限
     * @author 韦鹏
     * @date 2022/7/19 10:13
     * @param accountUser - 用户
     * @return org.springframework.security.core.userdetails.UserDetails
     **/
    public static UserDetails loadUserDetails(AccountUser accountUser) {
        if (Objects.isNull(accountUser)) {
            throw new UsernameNotFoundException(null);
        }
        AccountUserDetails sysUserDetails = new AccountUserDetails();
        BeanUtils.copyProperties(accountUser, sysUserDetails);
        List<AccountRole> roles = ACCOUNT_USER_ROLE_SERVICE.getUserRolesByUserId(accountUser.getId());
        Set<SimpleGrantedAuthority> authorities = roles.stream().map(e -> new SimpleGrantedAuthority(e.getName())).collect(Collectors.toSet());
        Set<String> permissions = roles.stream().map(AccountRole::getName).collect(Collectors.toSet());
        sysUserDetails.setAuthorities(authorities);
        sysUserDetails.setPermissions(permissions);
        return sysUserDetails;
    }
}
